"""今日头条签名算法实现

处理今日头条API的签名验证
"""
import hashlib
import time
import random
import json
from typing import Dict, Any, Optional
import logging

logger = logging.getLogger(__name__)


class ToutiaoSignature:
    """今日头条签名生成器"""
    
    def __init__(self):
        """初始化签名生成器"""
        # 头条的一些常量（这些可能会变化，需要定期更新）
        self.app_id = "1768"
        self.device_platform = "web"
        self.aid = "24"
        self.channel = "toutiao_web"
        
    def generate_signature(self, url: str, params: Dict[str, Any] = None) -> str:
        """生成签名
        
        Args:
            url: 请求URL
            params: 请求参数
            
        Returns:
            签名字符串
        """
        # 获取当前时间戳
        timestamp = int(time.time())
        
        # 构造签名原文
        sign_params = {
            "_signature": "",
            "timestamp": timestamp,
            **(params or {})
        }
        
        # 排序参数
        sorted_params = sorted(sign_params.items())
        
        # 构造签名字符串
        sign_str = "&".join([f"{k}={v}" for k, v in sorted_params])
        
        # 使用MD5生成签名（实际算法可能更复杂）
        signature = hashlib.md5(sign_str.encode()).hexdigest()
        
        logger.debug(f"Generated signature: {signature} for params: {sign_params}")
        
        return signature
    
    def generate_browser_fingerprint(self) -> str:
        """生成浏览器指纹
        
        Returns:
            浏览器指纹
        """
        # 模拟浏览器指纹
        fingerprint_data = {
            "screen_width": 1920,
            "screen_height": 1080,
            "color_depth": 24,
            "timezone_offset": -480,
            "language": "zh-CN",
            "platform": "Win32",
            "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        }
        
        # 生成指纹哈希
        fingerprint_str = json.dumps(fingerprint_data, sort_keys=True)
        fingerprint = hashlib.sha256(fingerprint_str.encode()).hexdigest()[:16]
        
        return fingerprint
    
    def generate_msToken(self, length: int = 128) -> str:
        """生成msToken
        
        Args:
            length: token长度
            
        Returns:
            msToken
        """
        chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
        token = ''.join(random.choice(chars) for _ in range(length))
        return token
    
    def generate_tt_webid(self) -> str:
        """生成tt_webid
        
        Returns:
            tt_webid
        """
        # 生成一个类似真实的webid
        webid = str(int(time.time() * 1000000) + random.randint(1000, 9999))
        return webid
    
    def get_signed_params(self, base_params: Dict[str, Any] = None) -> Dict[str, Any]:
        """获取带签名的完整参数
        
        Args:
            base_params: 基础参数
            
        Returns:
            带签名的参数
        """
        params = base_params or {}
        
        # 添加必要的参数
        params.update({
            "aid": self.aid,
            "app_name": "toutiao_web",
            "channel": self.channel,
            "device_platform": self.device_platform,
            "timestamp": int(time.time()),
            "msToken": self.generate_msToken(),
            "a_bogus": self.generate_browser_fingerprint(),
        })
        
        # 生成签名
        params["_signature"] = self.generate_signature("", params)
        
        return params
    
    def get_headers(self, referer: str = "https://www.toutiao.com") -> Dict[str, str]:
        """获取请求头
        
        Args:
            referer: 来源页面
            
        Returns:
            请求头字典
        """
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
            "Accept": "application/json, text/plain, */*",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
            "Accept-Encoding": "gzip, deflate, br",
            "Referer": referer,
            "Origin": "https://www.toutiao.com",
            "Sec-Fetch-Dest": "empty",
            "Sec-Fetch-Mode": "cors",
            "Sec-Fetch-Site": "same-origin",
            "Cookie": f"tt_webid={self.generate_tt_webid()}; "
                     f"msToken={self.generate_msToken()}; "
                     f"tt_webid_v2={self.generate_tt_webid()}"
        }
        
        return headers


class ToutiaoAPIHelper:
    """今日头条API辅助类"""
    
    def __init__(self):
        """初始化API辅助类"""
        self.signature = ToutiaoSignature()
        
    def get_hot_board_params(self) -> Dict[str, Any]:
        """获取热榜API参数
        
        Returns:
            API参数
        """
        base_params = {
            "origin": "toutiao_pc",
            "category": "hot_event"
        }
        
        return self.signature.get_signed_params(base_params)
    
    def get_feed_params(self, category: str = "__all__", max_behot_time: int = 0) -> Dict[str, Any]:
        """获取信息流API参数
        
        Args:
            category: 分类
            max_behot_time: 时间戳
            
        Returns:
            API参数
        """
        base_params = {
            "category": category,
            "max_behot_time": max_behot_time,
            "utm_source": "toutiao",
            "widen": 1,
            "tadrequire": "true"
        }
        
        return self.signature.get_signed_params(base_params)
    
    async def make_signed_request(self, session, url: str, params: Dict[str, Any] = None) -> Optional[Dict]:
        """发起带签名的请求
        
        Args:
            session: aiohttp会话
            url: 请求URL
            params: 请求参数
            
        Returns:
            响应数据
        """
        try:
            # 获取签名参数
            signed_params = self.signature.get_signed_params(params)
            
            # 获取请求头
            headers = self.signature.get_headers()
            
            # 发起请求
            async with session.get(url, params=signed_params, headers=headers) as response:
                if response.status == 200:
                    data = await response.json()
                    
                    # 检查响应状态
                    if data.get("message") == "success":
                        return data
                    else:
                        logger.warning(f"头条API返回错误: {data.get('message')}")
                else:
                    logger.error(f"请求失败，状态码: {response.status}")
                    
        except Exception as e:
            logger.error(f"请求头条API失败: {e}")
            
        return None


# 测试代码
if __name__ == "__main__":
    import asyncio
    import aiohttp
    
    async def test_signature():
        """测试签名生成"""
        helper = ToutiaoAPIHelper()
        
        # 测试获取热榜参数
        hot_params = helper.get_hot_board_params()
        print("热榜参数:", json.dumps(hot_params, indent=2))
        
        # 测试获取信息流参数
        feed_params = helper.get_feed_params()
        print("信息流参数:", json.dumps(feed_params, indent=2))
        
        # 测试实际请求
        async with aiohttp.ClientSession() as session:
            url = "https://www.toutiao.com/hot-event/hot-board/"
            result = await helper.make_signed_request(session, url, {"origin": "toutiao_pc"})
            
            if result:
                print(f"成功获取数据，热榜数量: {len(result.get('data', []))}")
            else:
                print("获取数据失败")
    
    asyncio.run(test_signature())